
#include "StdAfx.h"
#include "TreeTerrain.h"

#ifdef _WIN32
	#include <windows.h>
	#include <GL/gl.h>
	#include <GL/glu.h>
	#include "GLUT/glut.h"
#else
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#endif

namespace LifeSketchTree
{

CRawLoader CTerrain::barkTexture;
CRawLoader CTerrain::grassTexture;
CRawLoader CTerrain::dirtTexture;

CTerrain::CTerrain(void)
{
	size=0;
	_height=NULL;
	current_render_option=SURFACE_MODE;

	barkTexture.LoadFile("tree.raw");
	grassTexture.LoadFile("grass.raw");
	dirtTexture.LoadFile("dirt.raw");
}

CTerrain::CTerrain(int size)
{
	init(size);
	current_render_option=SURFACE_MODE;

	barkTexture.LoadFile("tree.raw");
	grassTexture.LoadFile("grass.raw");
	dirtTexture.LoadFile("dirt.raw");
}


CTerrain::~CTerrain(void)
{
	for(int i=0;i<size;i++) delete[] _height[i];						
	delete[] _height;						
}


void CTerrain::init(int mySize)
{
	size=mySize;
	int numVertices=size+1;
	_normal.setSize(numVertices,numVertices);

	_height=(float**) malloc(numVertices*sizeof(float*));
	if (_height==NULL) displayMessage(ERROR_MESSAGE, "CTerrain::CTerrain(n) could not allocate memory");
	int i;
	for(i=0;i<numVertices;i++)
	{
		_height[i]=(float*) malloc(numVertices*sizeof(float));
		if (_height[i]==NULL) displayMessage(ERROR_MESSAGE, "CTerrain::CTerrain(n) could not allocate memory");
	}
}


// In LifeSketch implementation the terrain for the tree 3D view is not displayed
// therefore the code to display the terrain is commented out. 
void CTerrain::display3D()
{
	float mat[4] = {0.29,0.91,0.24,1};
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat);
	glDisable(GL_LIGHTING);
	
	int i,j;
	glEnable(GL_NORMALIZE);
	glFrontFace(GL_CW);
	if (current_render_option==LINE_MODE)
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	else
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D, CTerrain::grassTexture.ID);

	glColor3f(0.2,1,0.2);
	glTranslatef(0,-0.2,0);
	
	glDisable(GL_TEXTURE_2D);
	
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBindTexture(GL_TEXTURE_2D, CTerrain::dirtTexture.ID);
	
	glFlush();
	
	glDisable(GL_TEXTURE_2D);
	glEnable(GL_LIGHTING);
	
	float mat2[4] = {0,0,0,1};
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat2);
	glMaterialfv(GL_FRONT, GL_SPECULAR, mat2);
	
}

float& CTerrain::height(int i, int j)
{
	if ((i<0) || (i>size) || (j<0) || (j>size))
		displayMessage(ERROR_MESSAGE, "CTerrain::CTerrain(n) invalid height field index (%d,%d)",i,j);
	else 
		return _height[i][j];
}

float* CTerrain::normal(int i, int j)
{
	if ((i<0) || (i>size) || (j<0) || (j>size))
		displayMessage(ERROR_MESSAGE, "CTerrain::CTerrain(n) invalid height field index (%d,%d)",i,j);
	else 
		return _normal(i,j);
}

void CTerrain::createDemoTerrain()
{
	int size=10;
	init(size);

	int i,j;
	float s,t;
	CVec3df v1,v2,n;
	for(i=0;i<=size;i++)
	{
		for(j=0;j<=size;j++)
		{	
			s=(float) i/(float) size;
			t=(float) j/(float) size;
			v1.setVector(1,0,0.12*s*2*Pi*cos(2*Pi*t));	
			v2.setVector(0,1,0.12*sin(2*Pi*t));	
			n=cross(v1,v2); 
			n.normaliseDestructive();

			normal(i,j)[0]=n[0];
			normal(i,j)[1]=n[1];
			normal(i,j)[2]=n[2];
			height(i,j)=0.2*sin(2*Pi*t)*s;
		}	
	}
}
}